/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package p2a;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.NetworkInterface;
import java.util.EventListener;
import java.util.EventObject;
import java.util.Random;
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.EventListenerList;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import jpcap.JpcapCaptor;
import jpcap.JpcapCaptor;
import jpcap.PacketReceiver;
import jpcap.packet.ICMPPacket;
import jpcap.packet.Packet;

/**
 *
 * @author user
 */
public class MainAppFrame extends JFrame {

    //threads 
    TestInputThread test_thread = new TestInputThread(0);
    //objects 
    Vector<Rule> rules = new Vector();
    Vector<TestCase> test_cases = new Vector();
    //PANEL
    MainApplicationPanel main_panel = new MainApplicationPanel();
    JMenuBar menuBar = new JMenuBar();
    JMenu file_menu = new JMenu("File");
    // tables
    /*
     * FILE MENU ITEMS
     */
    JMenuItem file_load_rules_menu = new JMenuItem("Load rules file");

    public MainAppFrame() {
        super();
        this.setTitle("P2A");
        /*
         * combobox
         */
        jpcap.NetworkInterface[] devices = JpcapCaptor.getDeviceList();

        for (int dev = 0; dev < devices.length; dev++) {
            main_panel.network_device_rx.addItem(devices[dev].description);
            main_panel.network_device_tx.addItem(devices[dev].description);
        }


        String[] rules_table_head = {"Order", "Protocol", "Source IP", "Source port", "Destiniation IP", "Destination Port", "Action"};
        String[] testcase_table_head = {"FW Rule", "Test case N", "Protocol", "Source IP", "Source port", "Destiniation IP", "Destination Port", "Flag", "Action", "result"};
        String[] testcase_types = {"ECP test", "C test"};

        for (int col = 0; col < testcase_types.length; col++) {
            main_panel.testcase_types.addItem(testcase_types[col]);
        }

        for (int col = 0; col < rules_table_head.length; col++) {
            main_panel.rules_table_model.addColumn(rules_table_head[col]);
        }

        for (int col = 0; col < testcase_table_head.length; col++) {
            main_panel.testcases_table_model.addColumn(testcase_table_head[col]);
        }

        file_menu.add(file_load_rules_menu);
        menuBar.add(file_menu);

        add(main_panel);
        this.setJMenuBar(menuBar);
        this.setSize(500, 500);

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


        /*
         * MENU LISTENER
         */
        file_load_rules_menu.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                JFileChooser fc = new JFileChooser();

                //fc.addChoosableFileFilter(new xmlFilter());

                int returnVal = fc.showOpenDialog(null);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    
                            while (main_panel.rules_table_model.getRowCount() > 0) {
            main_panel.rules_table_model.removeRow(0);
        }
                    File file = fc.getSelectedFile();
                    //This is where a real application would open the file.
                    System.out.println("Opening: " + file.getPath() + ".");
                    rules = XMLRulesParser.parseFromFile(file.getPath());
                    for (int i = 0; i < rules.size(); i++) {
                        //EcpTest ecp_test = new EcpTest();
                        //ecp_test.generateTestCasesFromRule(rules.get(i));
                        //CTest ctest = new CTest();
                        //ctest.generateTestCasesFromRule(rules.get(i));
                        String[] rowData = {String.valueOf(rules.get(i).getOrder()),
                            rules.get(i).getProtocol(), rules.get(i).getSrcIp(), rules.get(i).getSrcPort(),
                            rules.get(i).getDestIp(), rules.get(i).getDestPort(), rules.get(i).getAction()
                        };
                        main_panel.rules_table_model.addRow(rowData);
                    }
                }
            }
        });


        //buttons actions listener
        main_panel.testcases_b1.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                performSelectedTestCaseType();
            }
        });


        main_panel.rules_b1.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                analyseRules();
            }
        });

        main_panel.testcases_run.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {

                if (test_thread.isRunning()) {
                    test_thread.done();
                } else {
                    test_thread = new TestInputThread(main_panel.network_device_tx.getSelectedIndex());
                    test_thread.start();
                } // end 
            }
        });
    }

    public void analyseRules() {
        Vector<String> result = RulesAnalyse.Test(RulesAnalyse.ToRulesAux(rules));
        main_panel.rules_analysis_result.setText("");
        for (int i = 0; i< result.size(); i++)
            main_panel.rules_analysis_result.append(result.get(i)+ "\n");
    }

    public void performSelectedTestCaseType() {
        test_cases = new Vector();
        if (main_panel.testcase_types.getSelectedIndex() == 0) {
            EcpTest ecp_test = new EcpTest();
            test_cases = ecp_test.generateTestCasesFromRules(rules);
        } else if (main_panel.testcase_types.getSelectedIndex() == 1) {
            CTest ctest = new CTest();
            test_cases = ctest.generateTestCasesFromRules(rules);
        }
        while (main_panel.testcases_table_model.getRowCount() > 0) {
            main_panel.testcases_table_model.removeRow(0);
        }
        for (int tc = 0; tc < test_cases.size(); tc++) {
            String[] rowData = {String.valueOf(test_cases.get(tc).getRuleNmber()),
                String.valueOf(tc), test_cases.get(tc).getProtocol(), test_cases.get(tc).getSrcIp(), test_cases.get(tc).getSrcPort(),
                test_cases.get(tc).getDestIp(), test_cases.get(tc).getDestPort(), test_cases.get(tc).getFlag(), test_cases.get(tc).getAction(),
                test_cases.get(tc).getTestResult()
            };
            main_panel.testcases_table_model.addRow(rowData);
        }
    }

    //////////////////////////////////////////////////////
    
    
    class TestInputThread extends Thread implements Runnable {

        private boolean exec = false;
        private int deviceIndex;
        
        public TestInputThread(int deviceIndex)
        {
            super();
            this.deviceIndex = deviceIndex;
        }
        @Override
        public void run() {
            
                    main_panel.network_device_rx.setEnabled(false);
                    main_panel.network_device_tx.setEnabled(false);
                    main_panel.testcases_run.setText("Stop");
                    main_panel.testcases_b1.setEnabled(false);
                    main_panel.testcase_types.setEnabled(false);
                    
            exec = true;
  
        for (int test = 0; test < test_cases.size(); test++) {

            
            if(exec == false) return;
            
            boolean success = true;
            try {
                main_panel.testcases_table_model.setValueAt("testing", test, 9);
                //PacketGenerator.sendPacket(deviceIndex, test_cases.get(test));
                 new TestEngine().test(test_cases.get(test),main_panel.network_device_tx.getSelectedIndex(),main_panel.network_device_tx.getSelectedIndex());
                //mark current test by blue

            } catch (Exception e) {
                success = false;
                System.out.println("test " + test_cases.get(test).getTestCaseNumber() + " failed => " + e.getStackTrace());
                main_panel.testcases_table_model.setValueAt("Failed", test, 9);

            }
            if (success) {
                main_panel.testcases_table_model.setValueAt("Passed", test, 9);

            }

            //main_panel.test_cases_table.setDefaultRenderer(String.class, colorRenderer);
            //main_panel.testcases_table_model.fireTableDataChanged();
        }//for
        done();
        }
        public void done()
        {
            exec = false;
               main_panel.network_device_tx.setEnabled(true);
               main_panel.network_device_rx.setEnabled(true);
                    main_panel.testcases_run.setText("Run");
                    main_panel.testcases_b1.setEnabled(true);
                    main_panel.testcase_types.setEnabled(true);
                    
                    interrupt();
        }
        
        public boolean isRunning()
        {
            return exec;
        }
    }
}//end class
class xmlFilter extends javax.swing.filechooser.FileFilter {

    @Override
    public boolean accept(File file) {
        String filename = file.getName();
        return filename.endsWith(".xml");
    }

    @Override
    public String getDescription() {
        return "*.xml";
    }
}
